package service

import (
	"github.com/kataras/golog"
	"sdn-executor/config"
	"sdn-executor/storage/sql/executor"
	"sdn-executor/utils/erros"
	"time"

	"sdn-executor/core/engine"
	model "sdn-executor/model/cli"
	"sdn-executor/model/common"
)

func GetCLIResultByRequestID(requestId string) (*model.Result, error) {
	results, err := executor.QuerySdnExecutorResultByRequestId(requestId)
	if err != nil {
		return nil, err
	}

	var cmdResults []*model.CommandResult
	for _, result := range results[1:] {
		cmdResults = append(cmdResults, &model.CommandResult{
			Order:  result.Sequence,
			Status: common.ExecStatus(result.Status),
			Cmd:    result.Request,
			Echo:   result.Result,
		})
	}

	response := &model.Result{
		Code:      erros.CodeOK,
		Msg:       results[0].Reason,
		RequestId: requestId,
		Status:    common.ExecStatus(results[0].Status),
		Echos:     cmdResults,
	}

	return response, nil
}

func ExecuteCLICmd(query *model.Query) (any, *erros.Error) {

	// 获取或创建引擎
	e := engine.GetOrCreateEngine(query.Device)

	// 发送请求
	m := engine.NewMessage(engine.MsgTypeCLI, query.Priority, query.ReadOnly, query)
	err := e.SendRequestWithTimeout(query.Channel, m, config.C().CLI.QueueTimeoutMs*time.Millisecond)
	if err != nil {
		// 处理错误
		return nil, err
	}

	err = createSdnExecutorResult(query, &query.BaseQuery, m)
	if err != nil {
		return nil, err
	}

	// 等待结果
	timeout := query.AsyncTimeoutMs * time.Millisecond
	select {
	case r, ok := <-m.Response:
		if ok {
			return r, nil
		}

		return nil, erros.New(erros.CodeInternalError, "response channel closed unexpectedly")
	case <-time.After(timeout):
		golog.Info("AsyncTimeout")
		// 同步转异步
		result := model.Result{
			Code:      erros.CodeAsyncTimeout,
			Msg:       "please try to get result later",
			RequestId: m.RequestId,
			Status:    common.ExecStatusExecuting,
		}

		return result, nil
	}

}
